from nest.path.exception import MissingParser


class Path(object):

    @classmethod
    def get_parser_type(cls, meta):
        parser_type = meta.get_path_parser_type()
        if not parser_type:
            raise MissingParser()
        return parser_type

    @classmethod
    def get_instance(cls, meta, path):
        parser_type = cls.get_parser_type(meta)
        return parser_type(meta, path).get_iterator()

    @classmethod
    def resolve_path(cls, meta, path):
        if not isinstance(path, Path):
            path = cls.get_instance(meta, path)
        return path

    @classmethod
    def get_parent(cls, meta, path):
        '''
        @rtype: ParsedPath | PathKey
        '''
        path = cls.resolve_path(meta, path)
        parent_path = [key for key in path]
        parent_path.pop()
        return ParsedPath.simplify(parent_path)

    @classmethod
    def get_rest(cls, meta, path):
        '''
        @rtype: ParsedPath | PathKey
        '''
        path = cls.resolve_path(meta, path)
        rest_path = [key for key in path]
        # Reverse, remove last, reverse again.
        return ParsedPath.simplify(rest_path[::-1][:-1][::-1])

    @classmethod
    def get_tail(cls, meta, path):
        '''
        @rtype: ParsedPath | PathKey
        '''
        path = cls.resolve_path(meta, path)
        rest_path = [key for key in path]
        return ParsedPath.simplify(rest_path[::-1][0])

    @classmethod
    def get_join(cls, meta):
        parser_type = cls.get_parser_type(meta)
        return parser_type(meta, None).join


from nest.path.parsed import ParsedPath
